<?php

namespace App\Http\Admin\Services;

use App\Models\Admin\AdminUser;
use App\Models\Admin\Permission;
use App\Models\Admin\Role;
use Spatie\Permission\Guard;

class AdminRoleService extends BaseService
{

    /**
     * 权限名是否重复
     * @param string $name
     * @return void
     */
    public function nameRepetition(string $name)
    {
        return Role::where(['name' => $name, 'guard_name' => Guard::getDefaultName(self::class)])->first() ?? false;
    }


    /**
     * 角色列表
     * @param array $params
     * @return bool|array|null
     */
    public function list(array $params): bool|array|null
    {
        return $this->page($params,Role::query()) ?? null;
    }


    /**
     * 创建角色
     * @param array $role_data
     * @return mixed
     * @throws \App\Api\Exceptions\BusinessException
     */
    public function createRole(array $role_data): mixed
    {
        if ($this->nameRepetition($role_data['name']))
            $this->throwBusinessException(info: '角色名已存在');
        return \DB::transaction(function () use ($role_data) {
            // 校验是否授权
            if ($this->isExist($role_data, 'permissions')) {
                $permissions = $role_data['permissions'];
                unset($role_data['permissions']);
                return $this->syncPermissions(Role::create($role_data), $permissions);
            } else {
                return Role::create($role_data);
            }
        });

    }

    /**
     * 更新角色信息
     * @param array $update_data
     * @return bool
     * @throws \App\Api\Exceptions\BusinessException
     * @throws \Throwable
     */
    public function updateRole(array $update_data): bool
    {

        $role = Role::findOrFail($update_data['id']);
        // 校验角色名是否重复
        if ($this->isExist($update_data, 'name') && Role::where(['name' => $update_data['name'], 'guard_name' => Guard::getDefaultName(self::class)])->whereNot('id', $role['id'])->exists())
            $this->throwBusinessException(info: '角色名已存在');

        \DB::transaction(function () use ($role, $update_data): void {
            // 校验是否授权
            if ($this->isExist($update_data, 'permissions')) {
                $this->syncPermissions($role, $update_data['permissions']);
                unset($update_data['permissions']);
            }
            $role->update($update_data);
        });
        return true;
    }

    /**
     * 给角色授权权限
     * @param Role $role 角色ID
     * @param array $permissions 授权的ID数组
     * @return mixed
     */
    public function syncPermissions(Role $role, array $permissions): mixed
    {
        return $role->syncPermissions(Permission::whereIn('id', $permissions)->get());
    }

    /**
     * 获取指定ID的角色详情
     * @param int $id
     * @return mixed
     */
    public function info(int $id): mixed
    {
        $role = Role::findOrFail($id);
        $role['permission_ids'] = $role->permissions->mapWithKeys(function ($permission, $key) {
            return [$key => $permission->id];
        });
        unset($role['permissions']);
        return $role;
    }

    /**
     * 刪除角色
     * @param int $id 角色ID
     * @return void
     * @throws \App\Api\Exceptions\BusinessException
     * @throws \Throwable
     */
    public function deleteRole(int $id)
    {
        $role = Role::findOrFail($id);
        if (AdminUser::role($role)->exists())
            $this->throwBusinessException(info: '当前角色下还存在分配用户');
        \DB::transaction(function () use ($role) {
            $role->revokePermissionTo($role->permissions);
            $role->delete();
        });
    }

}
